package com.airshare;

import java.io.IOException;
import java.net.InetAddress;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.jmdns.*;
import javax.jmdns.impl.*;

// This class registers an instance of the Airshare
// file sharing service on all non-loopback network
// interfaces. This means our Airshare instance goes 'live'
// when register() is called.
// The name of the instance will be username._airshare._tcp.local.

// We are Also responsible for detecting other instances and
// maintaining a list of known peers

public class AirshareService implements ServiceListener {

	private Hashtable<String, JmDNS>  services = new Hashtable<String, JmDNS>();
	private Hashtable<String, ServiceInfo> infos = new Hashtable<String, ServiceInfo>();
	
	private Hashtable<String, ServiceInfo> discoveredServices = new Hashtable<String, ServiceInfo>();
	private UI ui;
	
	public AirshareService(UI ui){
		this.ui = ui;
	}
	
	public void register(final String name, final int port) {

		new Thread () {
			public void run() {
				try {
					threadedRegister(name, port);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}	
		}.start();
	}
	
	private void threadedRegister(final String name, final int port) throws IOException {
		NetworkTopologyDiscovery nt = new NetworkTopologyDiscoveryImpl();
		InetAddress[] address_list = nt.getInetAddresses();
		for(int i=0; i<address_list.length; ++i) {
			// Skip IP v6 for now
			if (address_list[i].getHostAddress().contains(":")) {
				continue;
			}
			// System.out.println("Registering on: " + address_list[i].getHostAddress());			
			JmDNS service = JmDNS.create(address_list[i], name);
			ServiceInfo srvInfo = ServiceInfo.create("_airshare._tcp.local.", name, port, "Airshare v1.0");
			service.registerService(srvInfo);
			service.addServiceListener("_airshare._tcp.local.", this);
			services.put(name, service);
			infos.put(name, srvInfo);
		}
	}

	// Unregister a service
	public void unregister(String name) {	
		JmDNS service = services.get(name);
		service.unregisterService(infos.get(name));
	}

	@Override
	public synchronized void serviceAdded(ServiceEvent evt) {
		
		//System.out.println("Service added " + evt.toString());
		ServiceInfo info = evt.getDNS().getServiceInfo(evt.getType(), evt.getName());
		discoveredServices.put(info.getName(), info);
		ui.addService(info);
	}

	@Override
	public synchronized void serviceRemoved(ServiceEvent evt) {	
		//System.out.println("Service Removed " + evt.toString());
		ServiceInfo info = evt.getInfo();
		//System.out.println("Service Info: " + info.toString());
		
		if (discoveredServices.containsKey(info.getName())) {
			discoveredServices.remove(info.getName());
		}
		ui.removeService(info);
	}

	@Override
	public void serviceResolved(ServiceEvent evt) {
	}
	
	// For debug only
	public void listServices() {
		System.out.println("Disvovered Services so far:");
		for(Enumeration<ServiceInfo> e=discoveredServices.elements(); e.hasMoreElements();) {
			System.out.println("Service: " + e.nextElement());
		}
	}
}